package com.pshcp.patient.api;

import cn.hutool.core.date.DateUtil;
import com.external.pay.PayService;
import com.external.pay.domain.PayPackageDTO;
import com.external.service.WsRequestService;
import com.external.ws.soap.entity.res.OrderRegisterRes;
import com.framework.base.PageList;
import com.framework.base.ResultBuilder;
import com.framework.base.ResultDTO;
import com.framework.exception.BizException;
import com.framework.logaop.Log;
import com.framework.logaop.LogSourceEnum;
import com.framework.logaop.LogTypeEnum;
import com.framework.thread.ReqComHold;
import com.framework.tool.CommonTool;
import com.pshcp.common.enums.RegPayStatusEnum;
import com.pshcp.common.enums.RegStatusEnum;
import com.pshcp.domain.model.Doctor;
import com.pshcp.domain.model.DoctorSchedule;
import com.pshcp.domain.model.OrderReg;
import com.pshcp.domain.model.Patient;
import com.pshcp.domain.model.PatientUser;
import com.pshcp.manager.messagenotification.MessageNotificationManager;
import com.pshcp.patient.business.OrderRegBusiness;
import com.pshcp.patient.domain.orderreg.ao.CancelRegAO;
import com.pshcp.patient.domain.orderreg.ao.ConfirmAO;
import com.pshcp.patient.domain.orderreg.ao.RefundRegAO;
import com.pshcp.patient.domain.orderreg.ao.RegDetailAO;
import com.pshcp.patient.domain.orderreg.ao.RegListAO;
import com.pshcp.patient.domain.orderreg.ao.ToPayAO;
import com.pshcp.patient.domain.orderreg.vo.RegDetailVO;
import com.pshcp.patient.tool.OrderRegTools;
import com.pshcp.service.DoctorScheduleService;
import com.pshcp.service.DoctorService;
import com.pshcp.service.OrderRegService;
import com.pshcp.service.PatientService;
import com.pshcp.service.PatientUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Date;

@Api(tags = {"患者端-挂号"})
@Slf4j
@RestController
@RequestMapping("/api/patient/orderReg")
public class OrderRegAPI {

    @Autowired
    private WsRequestService wsRequestService;

    @Autowired
    private OrderRegService orderRegService;

    @Autowired
    private OrderRegBusiness orderRegBusiness;

    @Autowired
    private DoctorScheduleService doctorScheduleService;

    @Autowired
    private DoctorService doctorService;

    @Autowired
    private PatientService patientService;

    @Autowired
    private MessageNotificationManager messageNotificationManager;

    @Autowired
    private PayService payService;

    @Autowired
    private PatientUserService patientUserService;

    @Value("${custom.desc.app-name}")
    private String appName;

    /**
     * 超时未支付时间
     */
    @Value("${custom.patient.un-pay-timeout:15}")
    private Integer unPayTimeout;

    @ApiOperation("挂号确认")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.ADD, desc = "挂号确认")
    @PostMapping("/confirm")
    public ResultDTO confirm(@RequestBody ConfirmAO confirmAO) throws BizException {

        DoctorSchedule doctorSchedule = doctorScheduleService.findById(confirmAO.getSchId());
        CommonTool.checkObj(doctorSchedule, "10120003");

        Doctor doctor = doctorService.findByHisDoctorId(doctorSchedule.getAccessDoctorId());
        CommonTool.checkObj(doctor, "10120001");

        Patient patient = patientService.findById(confirmAO.getPatientId());
        CommonTool.checkObj(patient, "10120002");

        OrderRegisterRes registerRes = wsRequestService.orderReg(OrderRegTools.buildWsDTO(doctorSchedule, patient.getHisPatientId(), confirmAO.getRegType(), patient));
        OrderReg orderReg = OrderRegTools.buildWsDTO2Model(registerRes);
        OrderRegTools.buildDoctorSchedule(orderReg, doctorSchedule);
        OrderRegTools.buildDoctorInfo(orderReg, doctor);
        OrderRegTools.buildPatientInfo(orderReg, patient);
        orderReg.setRegType(confirmAO.getRegType());
        orderReg.setHosName(appName);
        orderRegService.insert(orderReg);

        return ResultBuilder.success(orderReg.getId());
    }


    @ApiOperation("挂号单详情")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.SELECT, desc = "挂号单详情")
    @PostMapping("/regDetail")
    public ResultDTO<RegDetailVO> regDetail(@RequestBody RegDetailAO detailAO) throws BizException {

        OrderReg orderReg = orderRegService.findById(detailAO.getOrderRegId());
        CommonTool.checkObj(orderReg, "10170002");
        RegDetailVO detailVO = CommonTool.copyProperties(orderReg, RegDetailVO.class);
        detailVO.setExpireTime(DateUtil.offsetMinute(detailVO.getCreatedTime(), unPayTimeout));
        return ResultBuilder.success(detailVO);
    }

    @ApiOperation("挂号单列表")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.SELECT, desc = "挂号单列表")
    @PostMapping("/regList")
    public ResultDTO<PageList<RegDetailVO>> regList(@RequestBody RegListAO regListAO) {

        PageList<OrderReg> pageList = orderRegService.list(OrderRegTools.buildRegListAO2DTO(regListAO));

        return ResultBuilder.success(CommonTool.buildPageList(pageList, RegDetailVO.class));
    }

    @ApiOperation("去支付")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.UPDATE, desc = "去支付")
    @PostMapping("/toPay")
    public ResultDTO<PayPackageDTO> toPay(@RequestBody ToPayAO toPayAO) throws BizException {
        OrderReg orderReg = orderRegService.findById(toPayAO.getOrderRegId());
        if(!RegPayStatusEnum.WAIT_PAY.getCode().equals(orderReg.getPayStatus())){
            return ResultBuilder.failure("10170007");
        }
        if(BigDecimal.ZERO.compareTo(orderReg.getCost()) >= 0){
            orderRegBusiness.enterRegOrder(orderReg);
            PayPackageDTO payPackageDTO = new PayPackageDTO();
            payPackageDTO.setSkipPay(true);
            return ResultBuilder.success(payPackageDTO);
        }
        PatientUser patientUser = patientUserService.findById(ReqComHold.getReqCom().getUserId());
        toPayAO.setOpenid(patientUser.getOpenid());

        PayPackageDTO payPackageDTO = payService.callPay(OrderRegTools.buildPayDTO(orderReg, toPayAO));
        return ResultBuilder.success(payPackageDTO);
    }

    @ApiOperation("挂号订单退号(已支付)")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.UPDATE, desc = "挂号订单退号(已支付)")
    @PostMapping("/cancelReg")
    public ResultDTO cancelReg(@Valid @RequestBody RefundRegAO refundRegAO) throws BizException {
        OrderReg orderReg = orderRegService.findById(refundRegAO.getOrderRegId());

        if(!RegStatusEnum.PAY_SUCCESS.getCode().equals(orderReg.getRegStatus())){
            return ResultBuilder.failure("10170003");
        }
        orderReg.setCancelReason(refundRegAO.getCancelReason());
        return orderRegBusiness.refundRegOrder(orderReg);
    }

    @ApiOperation("挂号订单取消(未支付)")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.UPDATE, desc = "挂号订单取消(未支付)")
    @PostMapping("/cancelRegUnPay")
    public ResultDTO cancelRegUnPay(@RequestBody CancelRegAO cancelRegAO) throws BizException {
        OrderReg orderReg = orderRegService.findById(cancelRegAO.getOrderRegId());

        if(!RegStatusEnum.REG.getCode().equals(orderReg.getRegStatus())){
            return ResultBuilder.failure("10170005");
        }
        return orderRegBusiness.cancelRegOrder(orderReg);
    }

}
